Skip to content

Improve some ListenetSet gep descriptions #3978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

rikatz
Copy link
Contributor

@rikatz rikatz commented Aug 7, 2025

What type of PR is this?
/kind gep

What this PR does / why we need it:
This PR is a review of ListenerSet GEP, fixing some manifests and adding some comments to be further discussed

Which issue(s) this PR fixes:

Fixes #

Does this PR introduce a user-facing change?:

NONE

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. kind/gep PRs related to Gateway Enhancement Proposal(GEP) cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Aug 7, 2025
@k8s-ci-robot k8s-ci-robot requested a review from candita August 7, 2025 17:29
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: rikatz
Once this PR has been reviewed and has the lgtm label, please assign thockin for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Aug 7, 2025
Copy link
Member

@LiorLieberman LiorLieberman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Comment on lines 442 to 480

To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`:
```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httproute-example
spec:
parentRefs:
- name: some-workload-listeners
- name: second-workload-listeners
kind: ListenerSet
sectionName: second
- name: parent-gateway
kind: Gateway
sectionName: foo
```

To attach to listeners in both a `Gateway` and `ListenerSet` the route MUST have two `parentRefs`:
For instance, the following `HTTPRoute` attempts to attach to a listener defined in the parent `Gateway` using the sectionName `foo`. This is not valid and the route's status `Accepted` condition should be set to `False`

```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httproute-example
spec:
parentRefs:
- name: second-workload-listeners
kind: ListenerSet
sectionName: second
- name: parent-gateway
- name: some-workload-listeners
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess no real change here, just order, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, I wrote on my self review why I did the change. The example of the attachment of Gateway AND ListenerSet is more clear on this order, then we can go to the invalid examples :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make this invalid the kind needs to be a ListenerSet in the parentRef

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is still not clear to me, do you mean something like:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httproute-example
spec:
  parentRefs:
  - name: some-workload-listeners
    kind: ListenerSet
    sectionName: foo

?

Can you elaborate on this case with some example that would fail, I am not really understanding here. Thanks!

kind: Gateway
sectionName: foo
```
>--- Ricardo - above is a bit confusing, maybe ask Dave some clarification
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/cc @dprotaso

@k8s-ci-robot k8s-ci-robot requested a review from dprotaso August 7, 2025 17:37
kind: Gateway
sectionName: foo
```
>--- Ricardo - above is a bit confusing, maybe ask Dave some clarification
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dprotaso the example above is a bit confusing for me, probably because the API changed from when it was implemented.

I was wondering what it means for an HTTPRoute to try to attach a listener defined on a Gateway, using a section name foo. If this section name exists on the Gateway it is valid, right? eg.:

  listeners:
  - name: foo
    port: 80
    protocol: HTTP

So how can the situation above be invalid? Maybe we can get the full yaml definition, with Gateway, ListenerSet and HTTPRoute for clarification here?

Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rikatz
Copy link
Contributor Author

rikatz commented Aug 7, 2025

One extra question I have on ListenerSet that is not clear for me, is the deduplication of listeners from different namespaces.

Let me add an example:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: parent-gateway
  namespace: infra
spec:
  allowedListeners:
    namespaces:
      from: All
---
apiVersion: gateway.networking.x-k8s.io/v1alpha1
kind: ListenerSet
metadata:
  name: listener01
  namespace: user01
spec:
  parentRef:
    name: parent-gateway
    namespace: infra
    kind: Gateway
    group: gateway.networking.k8s.io
  listeners:
  - name: something
    hostname: something.foo.com
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        group: ""
        name: cert
---
apiVersion: gateway.networking.x-k8s.io/v1alpha1
kind: ListenerSet
metadata:
  name: listener01
  namespace: user02
spec:
  parentRef:
    name: parent-gateway
    namespace: infra
    kind: Gateway
    group: gateway.networking.k8s.io
  listeners:
  - name: something
    hostname: something.foo.com
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        group: ""
        name: othercert

Who owns something.foo.com here? because in this case, if we are not explicitly deduplicating, we may have a situation where 2 listeners for the same host and different cert are set.

@rikatz
Copy link
Contributor Author

rikatz commented Aug 7, 2025

on ListenerSet conflict management: at some point on this GEP there is a mention to it:

Listeners in a Gateway and their attached ListenerSets are concatenated as a list when programming the underlying infrastructure

Listeners should be merged using the following precedence:

    "parent" Gateway
    ListenerSet ordered by creation time (oldest first)
    ListenerSet ordered alphabetically by "{namespace}/{name}".

This is the statement for conflict management, but it is not really clear on what a conflict means. This way, during a discussion on gateway-api channel, we've reached the consensus of writing some conflict examples and how to deal with them, as part of the GEP, to make it easier on implementation and conformance.

@youngnick
Copy link
Contributor

Thanks @rikatz.

To bring the comments I had in the Slack thread here:

I think there should be two rules:

  • ListenerSets cannot be Accepted unless all Listeners are distinct (see the Gateway Spec listeners field for an exact definition).
  • If Listeners within a group of ListenerSets are not distinct (that is, if Listeners in different ListenerSet objects that attach to the same Gateway are not distinct), then the Listeners are conflicting, and the Listener from the oldest ListenerSet object wins and is Accepted. ListenerSets containing conflicting Listeners MUST set the Conflicted Condition to true and clearly indicate which Listeners are conflicted.

Examples that illustrate those rules would be awesome.

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Aug 11, 2025
@rikatz
Copy link
Contributor Author

rikatz commented Aug 11, 2025

@youngnick added some examples and a whole section for conflict management, let me know wdyt :)

@@ -115,6 +115,16 @@ type ListenerSetSpec struct {
// 2. ListenerSet ordered by creation time (oldest first)
// 3. ListenerSet ordered alphabetically by “{namespace}/{name}”.
//
// Regarding Conflict Management, Listeners in a ListenerSet follow the same
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add this new clause to the API types godoc?

Also we might want to call out sectionName behaves a bit differently where sibling ListenerSets can have the same sectionName.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, per Nick's suggestion I have used a similar approach of https://github.com/kubernetes-sigs/gateway-api/blob/main/apis/v1/gateway_types.go#L72 that contains the full description on godoc.

Conflicts are covered in the section 'ListenerConditions within a ListenerSet'
Conflicts are covered in the section [Listener and ListenerSet conflicts](#listener-and-listenerset-conflicts)

### Listener and ListenerSet conflicts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should combine this section into ListenerConditions within a ListenerSet so that conflicts are covered in one section.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO having a different section that defines what a conflict means from "what are the conditions" make it more clear for implementations.

We can probably refer on "ListenerConditions within a ListenerSet" back to the ### Listener and ListenerSet conflicts to define what a conflict means, but I think that adding all on a single "Conditions" section would overload it and make it confusing.

management.

With ListenerSet this validation should happen within the same ListenerSet resource,
but MUST be validated also within a Gateway scope and all of the attached Listeners/ListenerSets.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this language needs to exclude sectionName when comparing it across sibling Listeners

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or refer to 'Optional Section Name'

Copy link
Contributor Author

@rikatz rikatz Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry Dave, my brain is a bit fried today. Do you mean something like

"With ListenerSet this validation should happen within the same ListenerSet resource, but MUST be validated also within a Gateway scope and all of the attached Listeners/ListenerSets. The SectionName field is an exception for this validation, and while it should not conflict within the same ListenerSet, it can be duplicated between different ListenerSets" ?

protocol: HTTPS
port: 443
conditions:
- message: ListenerSet has conflicts with Gateway 'infra/parent-gateway'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we want to highlight the listener name in the error message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't wanted to leak cross namespace resource names

@rikatz rikatz force-pushed the listener-set-fixes branch from 48fdd71 to cb485fa Compare August 15, 2025 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. kind/gep PRs related to Gateway Enhancement Proposal(GEP) release-note-none Denotes a PR that doesn't merit a release note. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants